package main

import (
	"embed"
	"fmt"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
)

//go:embed dist
var distFiles embed.FS

func main() {

	Info("正在安装服务管理器...")

	// 创建临时目录
	// tmpDir := "/opt/youdu_plugin/coremail"
	tmpDir := filepath.Join(os.TempDir(), "services-manager-install")
	if err := os.RemoveAll(tmpDir); err != nil {
		Warning("清理临时目录失败: %v\n", err)
		os.Exit(1)
	}

	if err := os.MkdirAll(tmpDir, 0755); err != nil {
		Warning("创建临时目录失败: %v\n", err)
		os.Exit(1)
	}

	// 解压所有文件
	if err := extractFiles("dist", tmpDir, distFiles); err != nil {
		Warning("解压文件失败: %v\n", err)
		os.Exit(1)
	}

	// 执行安装脚本
	installScript := filepath.Join(tmpDir, "install.sh")
	if err := os.Chmod(installScript, 0755); err != nil {
		Warning("设置安装脚本权限失败: %v\n", err)
		os.Exit(1)
	}

	cmd := exec.Command("sudo", installScript)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		Warning("执行安装脚本失败: %v\n", err)
		os.Exit(1)
	}

	// 清理临时目录
	// if err := os.RemoveAll(tmpDir); err != nil {
	// 	Warning("清理临时目录失败: %v\n", err)
	// 	os.Exit(1)
	// }

	Info("安装完成!")
}

func extractFiles(prefix, destPath string, embedFS embed.FS) error {
	entries, err := fs.ReadDir(embedFS, prefix)
	if err != nil {
		return fmt.Errorf("读取嵌入文件失败: %v", err)
	}

	for _, entry := range entries {
		sourcePath := filepath.Join(prefix, entry.Name())
		targetPath := filepath.Join(destPath, entry.Name())

		if entry.IsDir() {
			if err := os.MkdirAll(targetPath, 0755); err != nil {
				return fmt.Errorf("创建目录失败 %s: %v", targetPath, err)
			}
			if err := extractFiles(sourcePath, targetPath, embedFS); err != nil {
				return err
			}
			continue
		}

		data, err := embedFS.ReadFile(sourcePath)
		if err != nil {
			return fmt.Errorf("读取文件失败 %s: %v", sourcePath, err)
		}

		if err := os.WriteFile(targetPath, data, 0644); err != nil {
			return fmt.Errorf("写入文件失败 %s: %v", targetPath, err)
		}
	}

	return nil
}

// Info should be used to describe the example commands that are about to run.
func Info(format string, args ...interface{}) {
	fmt.Printf("\x1b[34;1m%s\x1b[0m\n", fmt.Sprintf(format, args...))
}

// Warning should be used to display a warning
func Warning(format string, args ...interface{}) {
	fmt.Printf("\x1b[36;1m%s\x1b[0m\n", fmt.Sprintf(format, args...))
}
